'use strict';
const utils = require('@dou-gong-cli/utils');
const formatPath = require('@dou-gong-cli/format-path');
const {
  getDefaultRegistry,
  getNpmLatestVersion
} = require('@dou-gong-cli/get-npm-info');
const path = require('path');
const pkgDir = require('pkg-dir');
const pathExists = require('path-exists');
const log = require('@dou-gong-cli/log');
const fse = require('fs-extra');
const npminstall = require('npminstall');

class Package {
  constructor(options) {
    if (!options || !utils.isObject(options)) {
      throw new Error('Package类，构造函数options参数必传，切必须为对象。');
    }
    /** package 路径 */
    this.targetPath = options.targetPath;
    /** package 缓存路径 */
    this.storeDir = options.storeDir;
    /** package 名称 */
    this.packageName = options.packageName;
    /** package 版本号 */
    this.packageVersion = options.packageVersion;
  }

  /** 缓存文件路径 */
  get cacheFilePath() {
    return path.resolve(
      this.storeDir,
      `_${this.packageName.replace(/\//g, '_')}@${this.packageVersion}@${
        this.packageName
      }`
    );
  }

  /** 获取指定版本号缓存路径 */
  getSpecificVersionCachePath(version) {
    return path.resolve(
      this.storeDir,
      `_${this.packageName.replace(/\//g, '_')}@${version}@${this.packageName}`
    );
  }

  async prepare() {
    if (this.storeDir && !pathExists.sync(this.storeDir)) {
      fse.mkdirpSync(this.storeDir);
    }
    if (this.packageVersion === 'latest') {
      this.packageVersion = await getNpmLatestVersion(
        this.packageName,
        getDefaultRegistry(true)
      );
    }
  }

  /** 判断当前package是否存在 */
  async exists() {
    if (this.storeDir) {
      await this.prepare();
      return pathExists.sync(this.cacheFilePath);
    } else {
      return pathExists.sync(this.targetPath);
    }
  }

  /** 安装Package */
  async install() {
    log.info('package install', this.packageName);
    await this.prepare();
    // 在全局缓存目录中下载依赖包
    await npminstall({
      root: this.targetPath,
      storeDir: this.storeDir,
      pkgs: [
        {
          name: this.packageName,
          version: this.packageVersion
        }
      ],
      registry: getDefaultRegistry(true)
    }).catch((e) => {
      log.error(e);
    });
  }

  /** 更新Package */
  async update() {
    await this.prepare();
    // 1. 获取最新版本号
    // 2. 查询最新版本号 在缓存目录中是否存在
    // 3. 如果不存在，安装最新版本
    // 4. 如果存在 不用进行处理
    const latestVersion = await getNpmLatestVersion(this.packageName);
    const latestCachePath = this.getSpecificVersionCachePath(latestVersion);
    if (!pathExists.sync(latestCachePath)) {
      log.info('package update', this.packageName, this.packageVersion);
      await npminstall({
        root: this.targetPath,
        storeDir: this.storeDir,
        pkgs: [
          {
            name: this.packageName,
            version: latestVersion
          }
        ],
        registry: getDefaultRegistry(true)
      }).catch((e) => {
        log.error(e);
      });
      this.packageVersion = latestVersion;
    } else {
      this.packageVersion = latestVersion;
    }
  }

  /** 获取入口文件 */
  getRootFilePath() {
    function _getRootFilePath(targetPath) {
      // 1. 获取package.json所在目录
      // 2. 读取package.json require()
      // 3. 寻找main字段，找到入口文件
      // 4. 路径兼容(mac/windows)\
      const dir = pkgDir.sync(targetPath);
      if (dir) {
        const pkgFile = require(path.resolve(dir, 'package.json'));
        if (pkgFile && pkgFile.main) {
          return formatPath(path.resolve(dir, pkgFile.main));
        }
      }
      return null;
    }
    if (this.storeDir) {
      return _getRootFilePath(this.cacheFilePath);
    } else {
      return _getRootFilePath(this.targetPath);
    }
  }
}

module.exports = Package;
